
#ifndef _SUDOKU
#  define _SUDOKU

#  include <config.h>

#  include <sdk_list.h>
#  include <sdk_mem.h>
#  include <matrix.h>
#  include <stdlib.h>
#  include <string.h>

/* These define the actual sudoku structure: */
#  define SDK_SUB_MTX_SIZE  3
#  define SDK_SIZE (SDK_SUB_MTX_SIZE * SDK_SUB_MTX_SIZE)
#  define SDK_LOW_NUM 1
#  define SDK_HIGH_NUM (SDK_LOW_NUM + \
			(SDK_SUB_MTX_SIZE * SDK_SUB_MTX_SIZE) - 1)



/* Types for building the sudoku data structure. */

struct _sdk_square {

  int value;  // Only used if its been solved.
  int row;
  int col;
  sdk_list pos; // Possibilities.

};

typedef struct _sdk_square sdk_square;

struct _sdk_sudoku {

  sdk_square sdk_data[SDK_SIZE][SDK_SIZE];
  char solved;

};

typedef struct _sdk_sudoku sudoku;

typedef struct _sdk_sub_mtx {

  sdk_square sdk_data[SDK_SUB_MTX_SIZE][SDK_SUB_MTX_SIZE];
  char solved;

} sdk_sub_mtx;

typedef struct _sdk_rc {

  sdk_square sdk_data[SDK_SIZE];
  char solved;
  char remaining;
  char rc;

} sdk_rc;

typedef struct _sdk_sub_mtx_overlay {

  sdk_square *sdk_data[SDK_SUB_MTX_SIZE][SDK_SUB_MTX_SIZE];
  int r_offset;
  int c_offset;

} sdk_sub_mtx_overlay;

#  define SDK_ROW 0
#  define SDK_COL 1

/* Sudoku functions/macros. */

#  define SDK_SUDOKU_ALLOC() ((sudoku *) malloc(sizeof(sudoku)));	\
  _sdk_memory += sizeof(sudoku);
#  define SDK_SQUARE_ALLOC() ((sdk_square *) malloc(sizeof(sdk_square))); \
  _sdk_memory += sizeof(sdk_square);
#  define SDK_RC_ALLOC() ((sdk_rc *) malloc(sizeof(sdk_rc)));	\
  _sdk_memory += sizeof(sdk_rc);
#  define SDK_SUB_MTX_ALLOC() ((sdk_sub_mtx *) malloc(sizeof(sdk_sub_mtx))); \
  _sdk_memory += sizeof(sdk_sub_mtx);
#  define SDK_SUB_MTX_OVERLAY_ALLOC() ((sdk_sub_mtx_overlay *)		\
				       malloc(sizeof(sdk_sub_mtx_overlay))); \
  _sdk_memory += sizeof(sdk_sub_mtx_overlay);
#  define SDK_ELEM(SDK, ROW, COL) (SDK->sdk_data[ROW][COL])
#  define SDK_ELEM_VAL(SDK, ROW, COL) (SDK->sdk_data[ROW][COL].val)
#  define SDK_SET(SDK, ROW, COL, VAL) (memcpy(&(SDK->sdk_data[ROW][COL]), \
					      &(VAL), sizeof(sdk_square)))
#  define SDK_SET_VAL(SDK, ROW, COL, VAL) (SDK->sdk_data[ROW][COL].value = \
					   (int)VAL)

int           sdk_legit_sudoku(sudoku *);
int           sdk_solve(sudoku *);
sudoku       *sdk_copy_sudoku(sudoku *);
sudoku       *sdk_load_sudoku(char *);
sdk_sub_mtx  *sdk_enclosing_matrix(sudoku *, int, int);
void          sdk_update_values(sudoku *);
void          sdk_update_lists(sudoku *);
int           sdk_number_solutions(sudoku *);
int           sdk_check_sudoku(sudoku *);
int           sdk_full_sdk(sudoku *);
int           sdk_solvable(sudoku *);
void          sdk_free_sudoku(sudoku *);

/* Functions that trace out a tree for brute force solving hard ones. */

sudoku      *_sdk_rec_solve(sudoku *);

/* Some utility functions/macros. */

int          _sdk_flesh_sdk(sudoku *);
sudoku      *_sdk_matrix_to_sudoku(vm_matrix *);
int          _sdk_square_possibilities(sudoku *, int, int);
sdk_square  *_sdk_locate_branch_square(sudoku *);
sdk_sub_mtx *_sdk_sub_mtx(sudoku *, int, int);
sdk_rc      *_sdk_generate_rc(sudoku *, int, int);
void         _sdk_update_list(sudoku *, int, int);
void         _sdk_clean_sudoku(sudoku *);
void         _sdk_print_sdk_vals(sudoku *);
void         _sdk_print_pos_lists(sudoku *);
void         _sdk_print_sub_mtx(sdk_sub_mtx *);
void         _sdk_print_sub_mtx_lists(sdk_sub_mtx *);
void         _sdk_print_mtx_overlay(sdk_sub_mtx_overlay *);
void         _sdk_print_rc(sdk_rc *);

/* These functions are used by the test programs and are in sdk_util.c */

void         _sdk_die_msg(char *, int);

/* Sudoku generation functions */
void        _sdk_do_generate_sudoke(sudoku *);
sudoku      *sdk_generate_sudoku();

/* Sudoku solving functions */
vm_matrix *_sdk_valid_positions(sudoku *, int, int, int);
sdk_sub_mtx_overlay *_sdk_sub_mtx_overlay(sudoku *, int, int);


#endif
